package com.wuming.house.security;

import com.wuming.house.core.WumingRole;
import com.wuming.house.model.Member;
import com.wuming.house.service.MemberService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 网站后台用户身份验证,授权 Realm 组件
 *
 * @author StarZou
 * @since 2014年6月11日 上午11:35:28
 **/
@Component(value = "securityRealm")
public class SecurityRealm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(SecurityRealm.class);

    @Autowired
    private MemberService memberService;


    /**
     * 权限检查
     */
    /**
     * 为当前登录的Subject授予角色和权限
     *
     * @see 经测试:本例中该方法的调用时机为需授权资源被访问时
     * @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache
     * @see 个人感觉若使用了Spring3
     * .1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache
     * @see 比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Member user = SecurityHander.getCurrentUser();

        if (memberService.isAdministrator(user)) {//管理员
            //添加对应权限
            authorizationInfo.addRole("super:manage");
            //添加对应角色
        } else if (user.getRole() == WumingRole.WUMING_USERCENTER_ROLE_NORMAL_USER.ordinal()) {
            authorizationInfo.addRole("normal:manage");
        } else if (user.getRole() == WumingRole.WUMING_USERCENTER_ROLE_SECONDHOUSEMANAGER.ordinal()) {
            authorizationInfo.addRole("secondhouse:manage");
        } else if (user.getRole() == WumingRole.WUMING_USERCENTER_ROLE_DECORATEMANAGER.ordinal()) {
            authorizationInfo.addRole("decorate:manage");
        }
        return authorizationInfo;
    }

    /**
     * 验证当前登录的Subject
     *
     * @see 经测试:本例中该方法的调用时机为MemberController.login()方法中执行Subject.login()时
     * 实际上这个token是从MemberController里面currentUser.login(token)传过来的
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        String username = String.valueOf(token.getPrincipal());
        String password = "";
        Member user = null;
        if (null != username && username.startsWith("weixinuser_")) {//启动微信认证

        } else {//一般用户名密码认证
            password = new String((char[]) token.getCredentials());
            try {
                user = memberService.getMemberByNameAndPassword(username, password);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
        if (user == null) {
            throw new AuthenticationException("用户名或密码错误.");
        }
        // 此处无需比对,比对的逻辑Shiro会做,我们只需返回一个和令牌相关的正确的验证信息
        // 说白了就是第一个参数填登录用户名,第二个参数填合法的登录密码(可以是从数据库中取到的)
        // 这样一来,在随后的登录页面上就只有这里指定的用户和密码才能通过验证
        // 没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会在LoginController中抛出UnknownAccountException异常
        SecurityHander.setSession(SecurityHander.CURENTUSER, user);
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                username, password, getName());
        return authenticationInfo;
    }


}
